Expand description
C ABI compatible string types
While rust’s stdlib has some good basic options for C-string support, it has some glaring issues when dealing with C functions that accept or return arrays of structures containing C-string pointers or arrays. This crate aims to help fill that niche with safe, fast, ergonomic alternatives.
C type | ABI compatible Rust | null |
---|---|---|
const char * | abistr::CStrPtr | "" |
const char * | Option<abistr::CStrNonNull> | None |
const char * __attribute__((nonnull)) | abistr::CStrNonNull | ❌ undefined ❌ |
char struct_member[128]; | abistr::CStrBuf<u8, 128> | N/A |
C++20 | ABI compatible Rust | |
const char8_t * | abistr::CStrPtr<u8 > | "" |
const char16_t * | abistr::CStrPtr<u16> | "" |
const char32_t * | abistr::CStrPtr<u32> | "" |
const char8_t * | Option<abistr::CStrNonNull<u8 >> | None |
const char16_t * | Option<abistr::CStrNonNull<u16>> | None |
const char32_t * | Option<abistr::CStrNonNull<u32>> | None |
const char8_t * __attribute__((nonnull)) | abistr::CStrNonNull<u8 > | ❌ undefined ❌ |
const char16_t * __attribute__((nonnull)) | abistr::CStrNonNull<u16> | ❌ undefined ❌ |
const char32_t * __attribute__((nonnull)) | abistr::CStrNonNull<u32> | ❌ undefined ❌ |
char8_t struct_member[128]; | abistr::CStrBuf<u8, 128> | N/A |
char16_t struct_member[128]; | abistr::CStrBuf<u16, 128> | N/A |
char32_t struct_member[128]; | abistr::CStrBuf<u32, 128> | N/A |
iOS, OS X | ABI compatible Rust | |
const unichar * | abistr::CStrPtr<u16> | "" |
const wchar_t * | abistr::CStrPtr<u32> | "" |
const unichar * | Option<abistr::CStrPtr<u16>> | None |
const wchar_t * | Option<abistr::CStrPtr<u32>> | None |
const unichar * __attribute__((nonnull)) | abistr::CStrNonNull<u16> | ❌ undefined ❌ |
const wchar_t * __attribute__((nonnull)) | abistr::CStrNonNull<u32> | ❌ undefined ❌ |
unichar struct_member[128]; | abistr::CStrBuf<u16, 128> | N/A |
wchar_t struct_member[128]; | abistr::CStrBuf<u32, 128> | N/A |
Linux | ABI compatible Rust | |
const wchar_t * | abistr::CStrPtr<u32> | "" |
const wchar_t * | Option<abistr::CStrPtr<u32>> | None |
const wchar_t * __attribute__((nonnull)) | abistr::CStrNonNull<u32> | ❌ undefined ❌ |
wchar_t struct_member[128]; | abistr::CStrBuf<u32, 128> | N/A |
Windows | ABI compatible Rust | |
const wchar_t * | abistr::CStrPtr<u16> | "" |
const wchar_t * | Option<abistr::CStrPtr<u16>> | None |
const wchar_t * __attribute__((nonnull)) | abistr::CStrNonNull<u16> | ❌ undefined ❌ |
wchar_t struct_member[128]; | abistr::CStrBuf<u16, 128> | N/A |
Alternatives
*const c_char
- Pro: Can’t get any simpler for basic interop!
- Con: Requires
unsafe
to so much as shake a stick at. - Con: Easy to create undefined behavior by messing up edge cases involving null.
- Con: Easy to create undefined behavior by creating dangling pointers and other lifetime issues (raw pointers have no lifetimes.)
- Con: Fairly unergonomic to use directly.
- Pro: Relatively safe!
- Con: Immediate
O(n)
length check on construction, even if you never use the string. - Con: Being a DST (at least at the time of writing / rust 1.48.0), this isn’t ABI compatible with
*const c_char
and thus cannot be embedded in zero-conversion structures.
std::ffi::CString
- per &std::ffi::CStr
, but also:
- Pro: Dynamically allocated!
- Con: Dynamically allocated.
Macros
Create a &CStrNonNull
literal at compile time
Create a &CStrNonNull<u8>
literal at compile time
Create a &CStrNonNull<u16>
literal at compile time
Create a &CStrNonNull<u32>
literal at compile time
Structs
The buffer in question is too small to contain the string in question
Option<CStrNonNull<Unit>>
is ABI compatible with *const Unit
.
The string in question contains no terminal \0
, or contains an interior \0
.
The string in question contains an interior \0
.
The string in question contains no terminal \0
Traits
Treat self
as a C-style string
u8
/u16
/u32
, a rough analog to a Unicode Code Unit.